ARD2  RC2
Airbag Reference Demonstrator using MPC5604P
IntcInterrupts.c
00001 
00009 /*---------------------------------------------------------------------------*/
00010 /* By default we do not use nested interrupts, interrupts are handled in C.  */
00011 /* In case you want to use nested interrupts, set INTC_NESTED_INTERRUPT.     */
00012 /* In this case make sure all the needed registers are saved in the prolog   */
00013 /* and epilog of asm void INTC_INTCInterruptHandler(void)                    */ 
00014 /*---------------------------------------------------------------------------*/
00015 
00016 #ifndef INTC_NESTED_INTERRUPT
00017 #define INTC_NESTED_INTERRUPT 1
00018 #endif
00019 
00020 /*---------------------------------------------------------------------------*/
00021 /* Includes                                                                  */
00022 /*---------------------------------------------------------------------------*/
00023 
00024 #include "MPC5604P.h"           /* MPC55xx platform development header       */
00025 
00026 #include "IntcInterrupts.h"     /* Implement functions from this file */
00027 
00028 /*---------------------------------------------------------------------------*/
00029 /* Inline Assembler Defines                                                  */
00030 /*---------------------------------------------------------------------------*/
00031 
00033 #define MAKE_HLI_ADDRESS(hli_name, c_expr) /*lint -e753 */enum { hli_name=/*lint -e30*/((int)(c_expr)) /*lint -esym(749, hli_name) */ };
00034 
00036 MAKE_HLI_ADDRESS(INTC_IACKR, &INTC.IACKR.R)
00038 MAKE_HLI_ADDRESS(INTC_EOIR, &INTC.EOIR.R)
00039 
00041 MAKE_HLI_ADDRESS(INTC_MCR, &INTC.MCR.R)
00042 
00043 /*---------------------------------------------------------------------------*/
00044 /* Function Implementations                                                  */
00045 /*---------------------------------------------------------------------------*/
00046 
00048 #define INTC_INTERRUPTS_REQUEST_VECTOR_TABLE_SIZE (308*4)
00049 
00050 #pragma push /* Save the current state */
00051 #pragma section data_type ".__initialized_intc_handlertable" ".__uninitialized_intc_handlertable"
00052 /* The INTC vector table will be placed in RAM. 
00053    We will use the ".__uninitialized_intc_handlertable" name to do the 
00054    placement in the Linker Command File (.lcf) to avoid the initialization at
00055    startup time.  This will decrease the code size, but the table won't be 
00056    initialized to zero.
00057 */ 
00058 INTCInterruptFn INTCInterruptsHandlerTable[INTC_INTERRUPTS_REQUEST_VECTOR_TABLE_SIZE];
00059 #pragma pop
00060 
00061 #pragma push /* save the current state */
00062 #pragma force_active on
00063 #pragma function_align 16 /* We use 16 bytes alignment for Exception handlers */
00064 
00066 #if INTC_NESTED_INTERRUPT == 0
00067 
00068 __declspec(interrupt)
00069 __declspec(section ".__exception_handlers")
00070 void INTC_INTCInterruptHandler(void)
00071 {
00072     INTCInterruptFn *handlerFn = (INTCInterruptFn*)(*(unsigned int*)&INTC.IACKR.R);
00073 
00074     (**handlerFn)();
00075 
00076     INTC.EOIR.R = 0;
00077 }
00078 
00079 #else
00080 
00081 __declspec(interrupt)
00082 __declspec(section ".__exception_handlers")
00083 __asm void INTC_INTCInterruptHandler(void)
00084 {
00085 nofralloc
00086 prolog:
00087     stwu    r1, -0x50 (r1)    /* Create stack frame */
00088     stw r0,  0x24 (r1)        /* Store r0 working register  */
00089 
00090     /* Save SRR0 and SRR1 */
00091     mfsrr1  r0                /* Store SRR1 (must be done before enabling EE) */
00092     stw     r0,  0x10 (r1)
00093     mfsrr0  r0                /* Store SRR0 (must be done before enabling EE) */
00094     stw     r0,  0x0C (r1)
00095 
00096     /* Clear request to processor; r3 contains the address of the ISR */
00097     stw     r3,  0x28 (r1)    /* Store r3 */
00098     lis     r3, INTC_IACKR@h  /* Read pointer into ISR Vector Table & store in r3     */
00099     ori     r3, r3, INTC_IACKR@l
00100     lwz     r3, 0x0(r3)       /* Load INTC_IACKR, which clears request to processor   */
00101     lwz     r3, 0x0(r3)       /* Read ISR address from ISR Vector Table using pointer */
00102 
00103     /* Enable processor recognition of interrupts */
00104     wrteei  1                   /* Set MSR[EE]=1  */
00105 
00106     /* Save rest of context required by EABI */
00107     stw     r12, 0x4C (r1)      /* Store r12 */
00108     stw     r11, 0x48 (r1)      /* Store r11 */
00109     stw     r10, 0x44 (r1)      /* Store r10 */
00110     stw     r9,  0x40 (r1)      /* Store r9 */
00111     stw     r8,  0x3C (r1)      /* Store r8 */
00112     stw     r7,  0x38 (r1)      /* Store r7 */
00113     stw     r6,  0x34 (r1)      /* Store r6 */
00114     stw     r5,  0x30 (r1)      /* Store r5 */
00115     stw     r4,  0x2C (r1)      /* Store r4 */
00116     mfcr    r0                  /* Store CR */
00117     stw     r0,  0x20 (r1)
00118     mfxer   r0                  /* Store XER */
00119     stw     r0,  0x1C (r1)
00120     mfctr   r0                  /* Store CTR */
00121     stw     r0,  0x18 (r1)
00122     mflr    r0                  /* Store LR */
00123     stw     r0,  0x14 (r1)
00124 
00125     /* Branch to ISR handler address from SW vector table */
00126     mtlr    r3                  /* Store ISR address to LR to use for branching later */
00127     blrl                        /* Branch to ISR, but return here */
00128 
00129 epilog:
00130     /* Restore context required by EABI (except working registers) */
00131     lwz     r0,  0x14 (r1)      /* Restore LR */
00132     mtlr    r0
00133     lwz     r0,  0x18 (r1)      /* Restore CTR */
00134     mtctr   r0
00135     lwz     r0,  0x1C (r1)      /* Restore XER */
00136     mtxer   r0
00137     lwz     r0,  0x20 (r1)      /* Restore CR */
00138     mtcrf   0xff, r0
00139     lwz     r5,  0x30 (r1)      /* Restore r5 */
00140     lwz     r6,  0x34 (r1)      /* Restore r6 */
00141     lwz     r7,  0x38 (r1)      /* Restore r7 */
00142     lwz     r8,  0x3C (r1)      /* Restore r8 */
00143     lwz     r9,  0x40 (r1)      /* Restore r9 */
00144     lwz     r10, 0x44 (r1)      /* Restore r10 */
00145     lwz     r11, 0x48 (r1)      /* Restore r11 */
00146     lwz     r12, 0x4C (r1)      /* Restore r12 */
00147 
00148     /* Disable processor recognition of interrupts */
00149     wrteei  0
00150 
00151     /* Ensure interrupt flag has finished clearing */
00152     mbar    0
00153 
00154     /* Write 0 to INTC_EOIR, informing INTC to lower priority */
00155     li      r3, 0
00156     lis     r4, INTC_EOIR@h     /* Load upper half of INTC_EOIR address to r4 */
00157     ori     r4, r4, INTC_EOIR@l
00158     stw     r3, 0(r4)           /* Write 0 to INTC_EOIR */
00159 
00160     /* Restore Working Registers */
00161     lwz     r3,  0x28 (r1)      /* Restore r3 */
00162     lwz     r4,  0x2C (r1)      /* Restore r4 */
00163 
00164     /* Retrieve SRR0 and SRR1 */
00165     lwz     r0,  0x0C (r1)      /* Restore SRR0 */
00166     mtsrr0  r0
00167     lwz     r0,  0x10 (r1)      /* Restore SRR1 */
00168     mtsrr1  r0
00169 
00170     /* Restore Other Working Registers */
00171     lwz     r0,  0x24 (r1)      /* Restore r0 */
00172 
00173     /* Restore space on stack */
00174     addi    r1, r1, 0x50
00175 
00176     /* End of Interrupt */
00177     rfi
00178 }
00179 
00180 #endif
00181 
00182 #pragma force_active off
00183 #pragma pop
00184 
00190 void INTC_InstallINTCInterruptHandler(INTCInterruptFn handlerFn, unsigned short vectorNum,
00191                                       unsigned char psrPriority)
00192 {
00193     /* Set the function pointer in the ISR Handler table */
00194     INTCInterruptsHandlerTable[vectorNum] = handlerFn;
00195     /* Set the PSR Priority */
00196     INTC.PSR[vectorNum].B.PRI = psrPriority; 
00197 }
00198 
00203 __asm void INTC_InitINTCInterrupts( void )
00204 {
00205 nofralloc
00206 
00207     mflr    r29
00208 
00209     /* IVOR4 is for external interrupts (special purpose register #404)
00210     * This code enables the ISR handler for external interrupt code to address
00211     * INTC_INTCInterruptHandler (incl. large address by setting the IVPR value).
00212     */
00213     lis     r0, INTC_INTCInterruptHandler@h
00214     ori     r0, r0, INTC_INTCInterruptHandler@l
00215 
00216 #if !defined(Z0H_CORE)
00217     mtivor4 r0
00218 #else
00219     /* Set INTC.MCR = 0 VTES 4-bytes, HVEN - SW vector mode          */
00220     lis     r0,0
00221     lis     r3,INTC_MCR@ha 
00222     stw     r0, INTC_MCR@l(r3)
00223 #endif
00224 
00225     /* Enable external interrupts in the Machine State Register. Set MSR[EE]=1. */
00226     wrteei  1
00227 
00228     /* Set the location of the ISR Handler Table in INTC IACKR Register */
00229     lis     r0, INTCInterruptsHandlerTable@h
00230     ori     r0, r0, INTCInterruptsHandlerTable@l
00231     lis     r3,INTC_IACKR@h
00232     ori     r3,r3,INTC_IACKR@l
00233     stw     r0, 0(r3)
00234 
00235     mtlr    r29
00236 
00237     blr
00238 }
00239